# LogViewer class - Implements dialog that allows user to see logged events.
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import sys
import os
import string

try:
 	import pygtk
  	pygtk.require("2.4")
except:
  	pass
try:
	import gtk
  	import gtk.glade
except:
	sys.exit(1)
	
class LogViewer:
    """
    Implements dialog that allows user to see logged events.
    
    This dialog is used to check Entertainer logfiles. It reads all data from
    selected file and saves rows to self.log_rows. Then it filters unwanted
    rows away by calling self.filterMessages(). This method adds rows to
    ListStore, which is the model of TreeView object.
    
    Combobox and refresh -button actions read files again
    Checkbox actions just filter current rows again
    """
    
    # Is this dialog running as a stand alone process
    __STAND_ALONE = None
    
    # Class attributes
    COMBO_BACKEND_SELECTED = 0
    COMBO_FRONTEND_SELECTED = 1
    
    widgets = None
    dialog = None
    log_store = None
    log_rows = []

    gladefile = "utils/glade/log_dialog.glade"
    logfile_backend = os.path.expanduser('~/.entertainer/backend.log')
    logfile_frontend = os.path.expanduser('~/.entertainer/frontend.log')
    
    def __init__(self, stand_alone):
        self.__STAND_ALONE = stand_alone
        try:
            self.widgets = gtk.glade.XML(self.gladefile)
        except:
            self.logger.critical("Couldn't open glade file: " + self.gladefile)
            sys.exit(1)         
        callback_dic = { "on_close_log_button_clicked" : self.on_close_log_button_clicked,
                         "on_log_refresh_button_clicked" : self.updateLogRows,
                         "on_combobox_source_changed" : self.updateLogRows,
                         "on_checkbutton_debug_toggled" : self.filterMessages,
                         "on_checkbutton_critical_toggled" : self.filterMessages,
                         "on_checkbutton_error_toggled" : self.filterMessages,
                         "on_checkbutton_warning_toggled" : self.filterMessages,
                         "on_checkbutton_info_toggled" : self.filterMessages }
                         
        self.widgets.signal_autoconnect(callback_dic)
        
        # Set combobox to backend as default
        log_combo = self.widgets.get_widget("combobox_source")
        log_combo.set_active(self.COMBO_BACKEND_SELECTED)
        
        # Create log treeview
        treeview = self.widgets.get_widget("treeview_log")
        cell_renderer1 = gtk.CellRendererText()
        cell_renderer2 = gtk.CellRendererText()
        cell_renderer3 = gtk.CellRendererText()
        cell_renderer4 = gtk.CellRendererText()
        
        column1 = gtk.TreeViewColumn("Date")
        column1.pack_start(cell_renderer1, True)
        column1.set_attributes(cell_renderer1, text = 0)
        
        column2 = gtk.TreeViewColumn("Time")
        column2.pack_start(cell_renderer2, True)
        column2.set_attributes(cell_renderer2, text = 1)
        
        column3 = gtk.TreeViewColumn("Type")
        column3.pack_start(cell_renderer3, True)
        column3.set_attributes(cell_renderer3, text = 2)
        
        column4 = gtk.TreeViewColumn("Message")
        column4.pack_end(cell_renderer4, True)
        column4.set_attributes(cell_renderer4, text = 3)
        
        treeview.append_column(column1)
        treeview.append_column(column2)
        treeview.append_column(column3)
        treeview.append_column(column4)
        treeview.set_headers_visible(True)
        
        # Set model to view and read data from logfile
        self.log_store = gtk.ListStore(str, str, str, str)
        treeview.set_model(self.log_store)
        self.updateLogRows()
        
        # Show Log viewer dialog
        self.dialog = self.widgets.get_widget("LogDialog")
        self.dialog.resize(750,500)
        self.dialog.connect("destroy", self.on_close_log_button_clicked)
        self.dialog.show()
    
    def updateLogRows(self, widget=None):
        """Read logfile and udpate treeview"""
        log_combo = self.widgets.get_widget("combobox_source")
        self.log_rows[:] = []
        
        # Check should we show frontend or backend log
        if log_combo.get_active() == self.COMBO_BACKEND_SELECTED:
            try:
                for line in open(self.logfile_backend, 'r'):
                    try:
                        line_table = line.split()
                        message = string.join(line_table[3:], ' ')
                        row = line_table[:3] + [message]
                        self.log_rows.append(row)
                    except:
                        pass
            except:
                # No logfile available. We don't care :)
                pass
        elif log_combo.get_active() == self.COMBO_FRONTEND_SELECTED:
            try:
                for line in open(self.logfile_frontend, 'r'):
                    try:
                        line_table = line.split()
                        message = string.join(line_table[3:], ' ')
                        row = line_table[:3] + [message]
                        self.log_rows.append(row)
                    except:
                        pass
            except IOError:
                # No logfile available. We don't care :)
                pass
        self.log_rows.reverse() # Reverse so that the latest message is at top
        self.filterMessages() # Filter unwated message types
        
    def filterMessages(self, widget = None):
        """Checks which message types should be displayed on treeview"""
        if self.log_store:
            self.log_store.clear()

        debug = self.widgets.get_widget("checkbutton_debug").get_active()
        critical = self.widgets.get_widget("checkbutton_critical").get_active()
        error = self.widgets.get_widget("checkbutton_error").get_active()
        warning = self.widgets.get_widget("checkbutton_warning").get_active()
        info = self.widgets.get_widget("checkbutton_info").get_active()
        
        for element in self.log_rows:
            if element[2] == "DEBUG" and debug:
                self.log_store.append(element)
            elif element[2] == "CRITICAL" and critical:
                self.log_store.append(element)
            elif element[2] == "ERROR" and error:
                self.log_store.append(element)
            elif element[2] == "WARNING" and warning:
                self.log_store.append(element)
            elif element[2] == "INFO" and info:
                self.log_store.append(element)
                
# Signal handlers
    
    def on_close_log_button_clicked(self, widget):
        """
        If running as a stand alone process, quit. Otherwise only destroy dialog.
        """
        self.dialog.hide()
        self.dialog.destroy()
        if(self.__STAND_ALONE):
            gtk.main_quit()

